﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using corpus_platform.Data;

namespace corpus_platform.Services
{

    public class OntologySearchService : ISearchService<Ontology>
    {
        XElement root;
        XNamespace rdfns = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
        XNamespace owlns = "http://www.w3.org/2002/07/owl#";
        XNamespace rdfsns = "http://www.w3.org/2000/01/rdf-schema#";

        public string Namespace { get; set; }

        public string FilePath { get; set; }

        public List<Ontology> search(string searchTerm, SearchMode searchMode)
        {
            List<Ontology> ontologies = (from e in root.Elements(owlns + "NamedIndividual")
                                         where ((string)e.Attribute(rdfns + "about")).Contains(searchTerm)
                                         select new Ontology(
                                             getlocalName(e.Attribute(rdfns + "about").Value)
                                             ))
                                        .ToList();
            return ontologies;
        }

        public List<XElement> searchClass(string searchTerm)
        {
            List<XElement> elements = (from e in root.Elements(owlns + "Class")
                                       where e.Attribute(rdfns + "about").Value.Contains(searchTerm)
                                       select e).ToList();
            return elements;
        }

        public string getlocalName(string elementName)
        {
            if (elementName.Substring(0, Namespace.Length) == Namespace)
            {
                return elementName.Remove(0, Namespace.Length + 1);
            }
            else
            {
                throw new Exception("未找到命名空间");
            }

        }

        public string getfullName(string localName)
        {
            return $"{Namespace}#{localName}";
        }

        public XElement find(string localName)
        {
            var el = from e in root.Elements(owlns + "Class")
                     where (string)e.Attribute(rdfns + "about") == getfullName(localName)
                     select e;
            return el.First();
        }

        public List<XElement> searchInstance(string s)
        {
            List<XElement> els = (from e in root.Elements(owlns + "NamedIndividual")
                                  where e.Attribute(rdfns + "about").Value.Contains(s)
                                  select e).ToList();
            return els;
        }

        public bool hasParent(XElement element)
        {
            if (element.Element(rdfsns + "subClassOf") == null)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        public bool isA(XElement a, string b)
        {
            if (a.Attribute(rdfns + "about").Value == getfullName(b))
            {
                return true;
            }
            else if (!hasParent(a))
            {
                return false;
            }
            else
            {
                string pn = a.Element(rdfsns + "subClassOf").Attribute(rdfns + "resource").Value;
                var pe = from e in root.Elements(owlns + "Class")
                         where (string)e.Attribute(rdfns + "about") == pn
                         select e;
                return isA(pe.First(), b);
            }

        }


        public void addInstance(string instanceName, string type, string comment)
        {
            XElement element = new(owlns + "NamedIndividual");
            XAttribute attribute = new(rdfns + "about", getfullName(instanceName));
            element.Add(attribute);
            XElement setType = new(rdfns + "type");
            XAttribute setTypeAttribute = new(rdfns + "resource", getfullName(type));
            setType.Add(setTypeAttribute);
            element.Add(setType);
            XElement c = new(rdfsns + "commment", comment);
            element.Add(c);
            root.Add(element);
        }

        public void save(string filepath)
        {
            root.Save(filepath);
        }

        public void save()
        {
            root.Save(this.FilePath);
        }

        public void run()
        {
            try
            {
                root = XElement.Load(this.FilePath);
                Namespace = root.Element(owlns + "Ontology").Attribute(rdfns + "about").Value;
            }
            catch
            {
                throw new Exception("connect failed");
            }
        }
    }

}
